package com.colt.usercenter.service.user.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.colt.usercenter.dao.bonuseventlog.BonusEventLogMapper;
import com.colt.usercenter.dao.signRecord.SignRecordMapper;
import com.colt.usercenter.dao.user.UserMapper;
import com.colt.usercenter.domain.dto.message.UserUpdateBonusMsgDTO;
import com.colt.usercenter.domain.dto.user.UserLoginDTO;
import com.colt.usercenter.domain.dto.user.UserRegistorDTO;
import com.colt.usercenter.domain.dto.user.UserResponseDTO;
import com.colt.usercenter.domain.entity.bonuseventlog.BonusEventLog;
import com.colt.usercenter.domain.entity.signRecord.SignRecord;
import com.colt.usercenter.domain.entity.user.User;
import com.colt.usercenter.security.LoginException;
import com.colt.usercenter.security.RegistorExcepion;
import com.colt.usercenter.security.SignException;
import com.colt.usercenter.service.user.UserService;
import com.colt.usercenter.util.JwtOperator;
import com.colt.usercenter.util.RequestUtil;
import io.jsonwebtoken.Claims;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @program: user-center
 * @description: userservice
 * @author: colt
 * @create: 2020-05-02 10:22
 **/
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserServiceImpl implements UserService {


    private final UserMapper userMapper;
    private final BonusEventLogMapper bonusEventLogMapper;
    private final JwtOperator jwtOperator;
    private final SignRecordMapper signRecordMapper;
    public User Login(UserLoginDTO dto,String openid){
        User user = this.userMapper.selectOne(
                User.builder()
                        .wxId(openid).build()
        );
        if (null==user){
            User saveNewUser = User.builder()
                    .wxId(openid)
                    .avatarUrl(dto.getAvatarUrl())
                    .bonus(50)
                    .wxNickname(dto.getWxNickname())
                    .createTime(new Date())
                    .updateTime(new Date())
                    .roles("user")
                    .build();
            this.userMapper.insertSelective(saveNewUser);
            return saveNewUser;
        }
        return user;

    }
//    @Transactional(rollbackFor = Exception.class)
    public void costBonus(UserUpdateBonusMsgDTO updateBonusMsgDTO){
        /**
        * @Description: 用户积分换取分享 消费积分
        * @Param: [updateBonusMsgDTO] 
        * @return: void 
        * @Author: colt 
        * @Date: 2020/11/4 
        */
        //收取消息执行业务
//        1.为用户扣除积分
        Integer buyerId = updateBonusMsgDTO.getLoginId();
        Integer bonus = updateBonusMsgDTO.getBonus();
        //买家id
        User buyer = this.userMapper.selectByPrimaryKey(buyerId);
        User owner = this.userMapper.selectByPrimaryKey(updateBonusMsgDTO.getUserId());
        if (buyer==null&&buyer.getBonus()-bonus<0){
            throw new IllegalArgumentException("该用户信息存在异常！");
        }
        log.info("用户id:{},昵称：{},积分:{}",buyer.getId(),buyer.getWxNickname(),buyer.getBonus());
//        购买者扣减积分
        buyer.setBonus(buyer.getBonus()-bonus);
        this.userMapper.updateByPrimaryKeySelective(buyer);
//        分享者获得积分
        owner.setBonus(owner.getBonus()+bonus);
        this.userMapper.updateByPrimaryKeySelective(owner);
        log.info("扣减后bonus:{}",buyer.getBonus());
//        2.记录积分变更日志
        this.bonusEventLogMapper.insert(
                BonusEventLog.builder().event("SHARECOST")
                        .description("用户积分购买分享，扣除相应积分")
                        .createTime(new Date())
                        .userId(buyerId)
                        .value(bonus).build()
        );
        this.bonusEventLogMapper.insert(
                BonusEventLog.builder().event("SHARESELL")
                        .description("分享被购买，获得积分")
                        .createTime(new Date())
                        .userId(owner.getId())
                        .value(bonus).build()
        );
        log.info("积分修改完毕。。");
    }

    @Transactional(rollbackFor = Exception.class)
    public void addBonus(UserUpdateBonusMsgDTO updateBonusMsgDTO){
        /** 
        * @Description: 接收消息为用户添加积分 
        * @Param: [updateBonusMsgDTO] 
        * @return: void 
        * @Author: colt 
        * @Date: 2020/11/4 
        */ 
        //收到消息时执行的业务
        //1.为用户添加积分
        Integer userId = updateBonusMsgDTO.getUserId();
        Integer bonus = updateBonusMsgDTO.getBonus();
        User user = this.userMapper.selectByPrimaryKey(userId);
        if (null!=user){
            user.setBonus(user.getBonus()+updateBonusMsgDTO.getBonus());
        }

        this.userMapper.updateByPrimaryKeySelective(user);
        // this.userMapper.updateByPrimaryKey(user);
        //2.记录日志到bonus_event_log表里面
        this.bonusEventLogMapper.insert(
                BonusEventLog.builder().event(updateBonusMsgDTO.getEvent())
                        .description(updateBonusMsgDTO.getDescription())
                        .createTime(new Date())
                        .userId(userId)
                        .value(bonus).build()
        );

        log.info("积分添加完毕。。");
    }
    @Override
    public User findById(Integer id){
        return this.userMapper.selectByPrimaryKey(id);
    }

    public User query(User user) {
        return null;
    }

    public User findByUsername(UserRegistorDTO userRegistorDTO) {
        return userMapper.selectByUsername(userRegistorDTO.getUsername());
    }
    @Transactional(rollbackFor = Exception.class)
    public User insertUserInfo(UserRegistorDTO userRegistorDTO) {
        String password = userRegistorDTO.getPassword();
        if (password==null){
            throw new RegistorExcepion();
        }
        String s = Base64.decodeStr(password);
        String encodePwd = Base64.encode(password);
        User user = User.builder()
                .username(userRegistorDTO.getUsername())
                .roles("user")
                .bonus(50)
                .wxNickname("user_"+snowflake())
                .createTime(new Date())
                .updateTime(new Date())
                .signDate(new Date())
                .password(encodePwd)
                .build();
        userMapper.insertSelective(
                user
        );
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        signRecordMapper.insertSelective(SignRecord.builder()
                .continueSignMonth(0)
                .dateMonth(format.format(new Date()))
        .userId(user.getId())
        .build());
        return user;

    }


    @Transactional(rollbackFor = Exception.class)
    public User loginByUsername(UserRegistorDTO userLoginDTO) {
        User user = userMapper.selectByUsername(userLoginDTO.getUsername());
        if (user==null){
            throw new LoginException();
        }
        if(userLoginDTO.getUsername()==null&&userLoginDTO.getPassword()==null){
            throw new LoginException();
        }
        if (!userLoginDTO.getPassword().equals(Base64.decodeStr(user.getPassword()))){
            throw new LoginException();
        }

        return user;
    }
    // for 循环每次id不一样
    public long snowflake(){
        Snowflake snowflake = IdUtil.getSnowflake(3, 1);
        long id = snowflake.nextId();
        return id;
    }


    public UserResponseDTO sign() {
        HttpServletRequest request = RequestUtil.getHttpServletRequest();
        String token = request.getHeader("X-Token");
        Boolean isvalid = jwtOperator.validateToken(token);
        if (!isvalid){
            throw new SecurityException("token不合法或者已过期！");
        }
        Claims claims = jwtOperator.getClaimsFromToken(token);
        Integer id = (Integer) claims.get("id");
        System.err.println(id);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        User user = userMapper.selectByPrimaryKey(id);
//        若今天已经签过到了 不能再次签到
        if (format.format(user.getSignDate()).equals(format.format(new Date()))){
            throw new SignException();
        }
        /*在签到表中做记录
        * */
        SignRecord record = signRecordMapper.selectByPrimaryKey(user.getId());
        signRecordMapper.updateByPrimaryKeySelective(SignRecord.builder()
        .continueSignMonth(record.getContinueSignMonth()+1)
        .dateMonth(format.format(new Date()))
        .userId(user.getId())
        .build());
        user.setBonus(user.getBonus()+10);
        user.setSignDate(new Date());
        userMapper.updateByPrimaryKey(user);
        User updateUser = userMapper.selectByPrimaryKey(user.getId());
        return UserResponseDTO.builder()
                .bonus(updateUser.getBonus())
                .wxNickName(updateUser.getWxNickname())
                .id(updateUser.getId())
                .signDate(format.format(updateUser.getSignDate()))
                .build();
    }
}
